/* eslint-disable @typescript-eslint/no-explicit-any */
import CryptoJS from 'crypto-js'

// 签名工具函数
export async function signData(
  privateKey: CryptoKey,
  data: string,
): Promise<ArrayBuffer> {
  const dataArray = new TextEncoder().encode(data)
  return await window.crypto.subtle.sign(
    { name: 'RSASSA-PKCS1-v1_5' },
    privateKey,
    dataArray,
  )
}

export function pemToArrayBuffer(pem: string): ArrayBuffer {
  const b64Lines = pem
    .replace(/-----(BEGIN|END) (RSA )?PRIVATE KEY-----/g, '')
    .trim()
  const b64 = b64Lines.replace(/\n/g, '')
  const binaryString = atob(b64)
  const len = binaryString.length
  const bytes = new Uint8Array(len)
  for (let i = 0; i < len; i++) {
    bytes[i] = binaryString.charCodeAt(i)
  }
  return bytes.buffer
}

export async function importPrivateKey(pem: string): Promise<CryptoKey> {
  const keyData = pemToArrayBuffer(pem)
  return await window.crypto.subtle.importKey(
    'pkcs8',
    keyData,
    { name: 'RSASSA-PKCS1-v1_5', hash: { name: 'SHA-256' } },
    true,
    ['sign'],
  )
}

export function escapeSpecialChars(str: string): string {
  return str.replace(/&/g, '\\u0026')
}

export function createStringToSign(
  httpMethod: string,
  uri: string,
  timestamp: string,
  nonce: string,
  body: string,
): string {
  return `${httpMethod}\n${uri}\n${timestamp}\n${nonce}\n${escapeSpecialChars(body)}\n`
}

export function bufferToBase64(buffer: ArrayBuffer): string {
  let binary = ''
  const bytes = new Uint8Array(buffer)
  const len = bytes.byteLength
  for (let i = 0; i < len; i++) {
    binary += String.fromCharCode(bytes[i])
  }
  return btoa(binary)
}

export async function generateSignature(
  httpMethod: string,
  uri: string,
  timestamp: string,
  nonce: string,
  body: string,
): Promise<string> {
  const pemPrivateKey = import.meta.env.VITE_PEM_PRIVATE_KEY
  const stringToSign = createStringToSign(
    httpMethod,
    uri,
    timestamp,
    nonce,
    body,
  )
  const privateKey = await importPrivateKey(pemPrivateKey)
  const signature = await signData(privateKey, stringToSign)
  const signatureBase64 = bufferToBase64(signature)
  return `app_id=app_2c53369ef6d7b38,timestamp=${timestamp},nonce=${nonce},signature=${signatureBase64}`
}

// 工具函数
export function generateNonce(): string {
  return String(Math.floor(Math.random() * 90000) + 100000)
}

export function sortObjectKeys(obj: any): any {
  if (!obj || typeof obj !== 'object' || Array.isArray(obj)) return obj
  return Object.keys(obj)
    .sort()
    .reduce((sortedObj, key) => {
      sortedObj[key] = sortObjectKeys(obj[key])
      return sortedObj
    }, {} as any)
}

export const decryptData = (encryptedData: string): string => {
  const key = CryptoJS.enc.Utf8.parse('1234567890123456')
  const iv = CryptoJS.enc.Utf8.parse('1234567890123456')
  const decrypted = CryptoJS.AES.decrypt(encryptedData, key, {
    iv,
    mode: CryptoJS.mode.CBC,
  })
  return decrypted.toString(CryptoJS.enc.Utf8)
}
